home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / disk / diskHeader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-10  |  41.2 KB  |  1,455 lines

  1. /* 
  2.  * diskHeader.c --
  3.  *
  4.  *    Routines to read in the disk header information.
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/lib/disk/RCS/diskHeader.c,v 1.15 92/12/09 16:37:08 jhh Exp Locker: eklee $ SPRITE (Berkeley)";
  18. #endif not lint
  19.  
  20. #include "disk.h"
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24.  
  25. static Sun_DiskLabel     *ConvertToSunLabel();
  26. static Dec_DiskLabel    *ConvertToDecLabel();
  27. static Disk_Label    *ConvertFromSunLabel();
  28. static Disk_Label    *ConvertFromDecLabel();
  29. static short        SeeSunCheckSum();
  30. static int        CheckSunCheckSum();
  31. static int        MakeSunCheckSum();
  32.  
  33. /*
  34.  * BOOT_SECTOR        Where the boot sectors start on disk.
  35.  */
  36. #define    BOOT_SECTOR        1
  37. #define NUM_BOOT_SECTORS    15
  38.  
  39. /*
  40.  *----------------------------------------------------------------------
  41.  *
  42.  * Disk_ReadDecLabel --
  43.  *
  44.  *    Read the appropriate sector of a disk partition and see if its
  45.  *    a dec label.  If so, return a pointer to a Dec_DiskLabel.
  46.  *    Note:  This reads a Sprite-modified Dec label, which has
  47.  *    additional information.  If the label is a standard dec
  48.  *    label, the numHeads field will be set to -1 to indicate
  49.  *    the Sprite-dependent information is invalid.
  50.  *
  51.  * Results:
  52.  *    A pointer to the label data if could read it, 0 otherwise.
  53.  *
  54.  * Side effects:
  55.  *    Memory allocation.
  56.  *
  57.  *----------------------------------------------------------------------
  58.  */
  59. Dec_DiskLabel *
  60. Disk_ReadDecLabel(fileID)
  61.     int fileID;    /* Handle on raw disk */
  62. {
  63.     Address        buffer;
  64.     Dec_DiskLabel    *decLabelPtr;
  65.  
  66.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
  67.  
  68.     if (Disk_SectorRead(fileID, DEC_LABEL_SECTOR, 1, buffer) < 0) {
  69.     free((char *)buffer);
  70.     return((Dec_DiskLabel *)0);
  71.     } else {
  72.     decLabelPtr = (Dec_DiskLabel *)buffer;
  73.     if (decLabelPtr->magic != DEC_LABEL_MAGIC) {
  74.         free((char*)buffer);
  75.         return((Dec_DiskLabel *)0);
  76.     } else {
  77.         if (decLabelPtr->spriteMagic != FSDM_DISK_MAGIC) {
  78.         /* Original dec label, not Sprite modified dec label. */
  79.         decLabelPtr->numHeads = -1;
  80.         }
  81.         if (decLabelPtr->version != DEC_LABEL_VERSION) {
  82.         printf("Warning: Wrong dec label version: %x vs. %x\n",
  83.             decLabelPtr->version, DEC_LABEL_VERSION);
  84.         }
  85.         return(decLabelPtr);
  86.     }
  87.     }
  88. }
  89.  
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * Disk_ReadSunLabel --
  94.  *
  95.  *    Read the first sector of a disk partition and see if its
  96.  *    a sun label.  If so, return a pointer to a Sun_DiskLabel.
  97.  *
  98.  * Results:
  99.  *    A pointer to the super block data if could read it, 0 otherwise.
  100.  *
  101.  * Side effects:
  102.  *    Memory allocation.
  103.  *
  104.  *----------------------------------------------------------------------
  105.  */
  106. Sun_DiskLabel *
  107. Disk_ReadSunLabel(fileID)
  108.     int fileID;    /* Handle on raw disk */
  109. {
  110.     Address        buffer;
  111.     Sun_DiskLabel    *sunLabelPtr;
  112.  
  113.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
  114.  
  115.     if (Disk_SectorRead(fileID, 0, 1, buffer) < 0) {
  116.     free((char *)buffer);
  117.     return((Sun_DiskLabel *)0);
  118.     } else {
  119.     sunLabelPtr = (Sun_DiskLabel *)buffer;
  120.     if (sunLabelPtr->magic != SUN_DISK_MAGIC) {
  121.         fprintf(stderr, 
  122.             "Disk_ReadSunLabel: Bad magic 0x%x, should be 0x%x\n",
  123.             sunLabelPtr->magic, SUN_DISK_MAGIC);
  124.         free((char*)buffer);
  125.         return((Sun_DiskLabel *)0);
  126.     } else {
  127.         return(sunLabelPtr);
  128.     }
  129.     }
  130. }
  131.  
  132. /*
  133.  *----------------------------------------------------------------------
  134.  *
  135.  * Disk_ReadDiskHeader --
  136.  *
  137.  *    Read the super block and return a pointer to it.
  138.  *
  139.  * Results:
  140.  *    A pointer to the super block data if could read it, 0 otherwise.
  141.  *
  142.  * Side effects:
  143.  *    Memory allocation.
  144.  *
  145.  *----------------------------------------------------------------------
  146.  */
  147. Fsdm_DiskHeader *
  148. Disk_ReadDiskHeader(openFileID)
  149.     int openFileID;    /* Handle on raw disk */
  150. {
  151.     Address        buffer;
  152.     Fsdm_DiskHeader    *diskHeaderPtr;
  153.  
  154.     buffer = (Address) malloc(DEV_BYTES_PER_SECTOR);
  155.  
  156.     if (Disk_SectorRead(openFileID, 0, 1, buffer) < 0) {
  157.     return((Fsdm_DiskHeader *)0);
  158.     } else {
  159.     diskHeaderPtr = (Fsdm_DiskHeader *)buffer;
  160.     if (diskHeaderPtr->magic != FSDM_DISK_MAGIC) {
  161.         return((Fsdm_DiskHeader *)0);
  162.     } else {
  163.         return(diskHeaderPtr);
  164.     }
  165.     }
  166. }
  167.  
  168. /*
  169.  *----------------------------------------------------------------------
  170.  *
  171.  * Disk_ReadDomainHeader --
  172.  *
  173.  *    Read the domain header and return a pointer to it.
  174.  *
  175.  * Results:
  176.  *    A pointer to the domain header if could read it, NULL otherwise.
  177.  *
  178.  * Side effects:
  179.  *    Memory allocation.
  180.  *
  181.  *----------------------------------------------------------------------
  182.  */
  183. Ofs_DomainHeader *
  184. Disk_ReadDomainHeader(fileID, diskLabelPtr)
  185.     int fileID;            /* Stream to raw disk */
  186.     Disk_Label *diskLabelPtr;    /* Disk label */
  187. {
  188.     Ofs_DomainHeader    *headerPtr;
  189.  
  190.     headerPtr = (Ofs_DomainHeader *)malloc((unsigned) 
  191.     (diskLabelPtr->numDomainSectors * DEV_BYTES_PER_SECTOR));
  192.  
  193.     if (Disk_SectorRead(fileID, diskLabelPtr->domainSector,
  194.                     diskLabelPtr->numDomainSectors,
  195.                     (Address)headerPtr) < 0) {
  196.     return((Ofs_DomainHeader *)0);
  197.     } else {
  198.     if (headerPtr->magic != OFS_DOMAIN_MAGIC) {
  199.         fprintf(stderr, "Disk_ReadDomainHeader, bad magic <%x>\n",
  200.             headerPtr->magic);
  201.         free((Address)headerPtr);
  202.         return((Ofs_DomainHeader *)0);
  203.     } else {
  204.         return(headerPtr);
  205.     }
  206.     }
  207. }
  208.  
  209. /*
  210.  *----------------------------------------------------------------------
  211.  *
  212.  * Disk_WriteDomainHeader --
  213.  *
  214.  *    Write the domain header.
  215.  *
  216.  * Results:
  217.  *    SUCCESS if write succeeded, FAILURE otherwise
  218.  *
  219.  * Side effects:
  220.  *    None.
  221.  *
  222.  *----------------------------------------------------------------------
  223.  */
  224. ReturnStatus
  225. Disk_WriteDomainHeader(fileID, diskLabelPtr, headerPtr)
  226.     int         fileID;            /* Stream to raw disk */
  227.     Disk_Label         *diskLabelPtr;        /* Disk label */
  228.     Ofs_DomainHeader    *headerPtr;        /* Domain header. */
  229. {
  230.  
  231.     return Disk_SectorWrite(fileID, diskLabelPtr->domainSector,
  232.             diskLabelPtr->numDomainSectors, (Address)headerPtr);
  233. }
  234.  
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * Disk_ReadSummaryInfo --
  239.  *
  240.  *    Read the summary information and return a pointer to it.
  241.  *
  242.  * Results:
  243.  *    A pointer to the summary information if it could be read,
  244.  *    NULL otherwise.
  245.  *
  246.  * Side effects:
  247.  *    Memory allocation.
  248.  *
  249.  *----------------------------------------------------------------------
  250.  */
  251. Ofs_SummaryInfo *
  252. Disk_ReadSummaryInfo(fileID, diskLabelPtr)
  253.     int fileID;            /* Stream to raw disk */
  254.     Disk_Label *diskLabelPtr;    /* Disk label */
  255. {
  256.     Ofs_SummaryInfo *summaryPtr;
  257.  
  258.     summaryPtr = (Ofs_SummaryInfo *) malloc (sizeof(Ofs_SummaryInfo));
  259.  
  260.     if (Disk_SectorRead(fileID, diskLabelPtr->summarySector, 
  261.         diskLabelPtr->numSummarySectors, (Address)summaryPtr) < 0) {
  262.     return((Ofs_SummaryInfo *)0);
  263.     } else {
  264.     return(summaryPtr);
  265.     }
  266. }
  267.  
  268. /*
  269.  *----------------------------------------------------------------------
  270.  *
  271.  * Disk_WriteSummaryInfo --
  272.  *
  273.  *    Write the summary information.
  274.  *
  275.  * Results:
  276.  *    SUCCESS if write succeeded, FAILURE otherwise
  277.  *
  278.  * Side effects:
  279.  *    The summary information is written to the disk.
  280.  *
  281.  *----------------------------------------------------------------------
  282.  */
  283. ReturnStatus
  284. Disk_WriteSummaryInfo(fileID, diskLabelPtr, summaryPtr)
  285.     int fileID;            /* Stream to raw disk */
  286.     Disk_Label *diskLabelPtr;    /* Disk label */
  287.     Ofs_SummaryInfo *summaryPtr; /* Summary information */
  288. {
  289.     return Disk_SectorWrite(fileID, diskLabelPtr->summarySector,
  290.         diskLabelPtr->numSummarySectors, (Address)summaryPtr);
  291. }
  292. /*
  293.  *----------------------------------------------------------------------
  294.  *
  295.  * Disk_WriteDecLabel --
  296.  *
  297.  *    Write a DEC label to the appropriate sector of a disk partition.
  298.  *
  299.  * Results:
  300.  *    SUCCESS if write succeeded, FAILURE otherwise
  301.  *
  302.  * Side effects:
  303.  *    The label is written to the disk.
  304.  *
  305.  *----------------------------------------------------------------------
  306.  */
  307. ReturnStatus
  308. Disk_WriteDecLabel(fileID, labelPtr)
  309.     int         fileID;        /* Handle on raw disk */
  310.     Dec_DiskLabel     *labelPtr;     /* Ptr to DEC label */
  311. {
  312.     return Disk_SectorWrite(fileID, DEC_LABEL_SECTOR, 1, (Address) labelPtr);
  313. }
  314.  
  315. /*
  316.  *----------------------------------------------------------------------
  317.  *
  318.  * Disk_WriteSunLabel --
  319.  *
  320.  *    Write a Sun label to the appropriate sector of a disk partiton.
  321.  *
  322.  * Results:
  323.  *    0 if write succeeded, -1 otherwise
  324.  *
  325.  * Side effects:
  326.  *    The label is written to the disk.
  327.  *
  328.  *----------------------------------------------------------------------
  329.  */
  330. int
  331. Disk_WriteSunLabel(fileID, labelPtr)
  332.     int         fileID;        /* Handle on raw disk */
  333.     Sun_DiskLabel    *labelPtr;    /* Ptr to Sun label */
  334. {
  335.     return Disk_SectorWrite(fileID, 0, 1, (Address) labelPtr);
  336. }
  337.  
  338. /*
  339.  *----------------------------------------------------------------------
  340.  *
  341.  * Disk_ReadLabel --
  342.  *
  343.  *    Read a label off the disk and convert it to a Disk_Label.
  344.  *
  345.  * Results:
  346.  *    Pointer to Disk_Label if the label was read and converted,
  347.  *    NULL otherwise.
  348.  *
  349.  * Side effects:
  350.  *    Memory allocation.
  351.  *
  352.  *----------------------------------------------------------------------
  353.  */
  354.  
  355. Disk_Label *
  356. Disk_ReadLabel(fileID)
  357.     int fileID;            /* Handle on raw disk */
  358. {
  359.     Sun_DiskLabel    *sunLabelPtr;
  360.     Dec_DiskLabel    *decLabelPtr;
  361.  
  362.     sunLabelPtr = Disk_ReadSunLabel(fileID);
  363.     if (sunLabelPtr != (Sun_DiskLabel *)0) {
  364.     return ConvertFromSunLabel(fileID, sunLabelPtr);
  365.     } 
  366.     decLabelPtr = Disk_ReadDecLabel(fileID);
  367.     if (decLabelPtr != (Dec_DiskLabel *)0) {
  368.     return ConvertFromDecLabel(fileID, decLabelPtr);
  369.     }
  370.     return NULL;
  371. }
  372.  
  373. /*
  374.  *----------------------------------------------------------------------
  375.  *
  376.  * Disk_WriteLabel --
  377.  *
  378.  *    Converts a Disk_Label into a machine-specific disk label and
  379.  *    writes it on the disk.
  380.  *
  381.  * Results:
  382.  *    0 if everything worked
  383.  *    -1 if the label could not be converted
  384.  *    -2 otherwise
  385.  *
  386.  * Side effects:
  387.  *    A label is written on the disk.
  388.  *    Memory allocation.
  389.  *
  390.  *----------------------------------------------------------------------
  391.  */
  392.  
  393. int
  394. Disk_WriteLabel(fileID, labelPtr)
  395.     int         fileID;        /* Handle on raw disk */
  396.     Disk_Label        *labelPtr;     /* Ptr to label to write. */
  397. {
  398.     int            status;    
  399.  
  400.     switch(labelPtr->labelType) {
  401.     case DISK_SUN_LABEL: {
  402.         Sun_DiskLabel    *sunLabelPtr;
  403.         sunLabelPtr = ConvertToSunLabel(labelPtr);
  404.         if (sunLabelPtr == NULL) {
  405.         return -1;
  406.         }
  407.         status = Disk_WriteSunLabel(fileID, sunLabelPtr);
  408.         free((char *) sunLabelPtr);
  409.         if (status < 0) {
  410.         return -2;
  411.         }
  412.         break;
  413.     }
  414.     case DISK_DEC_LABEL: {
  415.         Dec_DiskLabel    *decLabelPtr;
  416.         decLabelPtr = ConvertToDecLabel(labelPtr);
  417.         if (decLabelPtr == NULL) {
  418.         return -1;
  419.         }
  420.         status = Disk_WriteDecLabel(fileID, decLabelPtr);
  421.         free((char *) decLabelPtr);
  422.         if (status < 0) {
  423.         return -2;
  424.         }
  425.         break;
  426.     }
  427.     default :
  428.         fprintf(stderr, "Unknown label type %d\n", labelPtr->labelType);
  429.         return -1;
  430.         break;
  431.     }
  432.     return 0;
  433. }
  434.  
  435. /*
  436.  *----------------------------------------------------------------------
  437.  *
  438.  * Disk_NewLabel --
  439.  *
  440.  *    Creates a new disk label.
  441.  *
  442.  * Results:
  443.  *    NULL if there was an error, a new disk label otherwise.
  444.  *
  445.  * Side effects:
  446.  *    Memory allocation
  447.  *
  448.  *----------------------------------------------------------------------
  449.  */
  450.  
  451. Disk_Label *
  452. Disk_NewLabel(labelType) 
  453.     Disk_NativeLabelType    labelType;    /* Native type of label. */
  454. {
  455.     Disk_Label        *labelPtr;
  456.  
  457.     labelPtr = (Disk_Label *) malloc(sizeof(Disk_Label));
  458.     if (labelPtr == NULL) {
  459.     fprintf(stderr, "Disk_NewLabel: Out of memory.\n");
  460.     return NULL;
  461.     }
  462.     bzero((char *) labelPtr, sizeof(Disk_Label));
  463.     strcpy(labelPtr->asciiLabel, "New label");
  464.     switch(labelType) {
  465.     case DISK_SUN_LABEL: 
  466.         labelPtr->asciiLabelLen = 128;
  467.         labelPtr->numPartitions = SUN_NUM_DISK_PARTS;
  468.         labelPtr->bootSector = SUN_BOOT_SECTOR;
  469.         labelPtr->numBootSectors = SUN_SUMMARY_SECTOR - SUN_BOOT_SECTOR -1;
  470.         labelPtr->summarySector = SUN_SUMMARY_SECTOR;
  471.         labelPtr->numSummarySectors = 1;
  472.         labelPtr->domainSector = SUN_DOMAIN_SECTOR;
  473.         labelPtr->numDomainSectors = OFS_NUM_DOMAIN_SECTORS;
  474.         labelPtr->labelType = labelType;
  475.         labelPtr->labelPtr = NULL;
  476.         labelPtr->labelSector = SUN_LABEL_SECTOR;
  477.         break;
  478.     case DISK_DEC_LABEL: 
  479.         labelPtr->asciiLabelLen = 128;
  480.         labelPtr->numPartitions = DEC_NUM_DISK_PARTS;
  481.         labelPtr->bootSector = DEC_BOOT_SECTOR;
  482.         labelPtr->numBootSectors = DEC_SUMMARY_SECTOR - DEC_BOOT_SECTOR -1;
  483.         labelPtr->summarySector = DEC_SUMMARY_SECTOR;
  484.         labelPtr->numSummarySectors = 1;
  485.         labelPtr->domainSector = DEC_DOMAIN_SECTOR;
  486.         labelPtr->numDomainSectors = OFS_NUM_DOMAIN_SECTORS;
  487.         labelPtr->labelType = labelType;
  488.         labelPtr->labelPtr = NULL;
  489.         labelPtr->labelSector = DEC_LABEL_SECTOR;
  490.         break;
  491.     default : 
  492.         fprintf(stderr, "Unknown label type %d\n", labelType);
  493.         free((char *) labelPtr);
  494.         labelPtr = NULL;
  495.         break;
  496.     }
  497.     return labelPtr;
  498. }
  499.  
  500.  
  501.  
  502. /*
  503.  *----------------------------------------------------------------------
  504.  *
  505.  * ConvertFromSunLabel --
  506.  *
  507.  *    Makes a Disk_Label from a Sun_DiskLabel
  508.  *
  509.  * Results:
  510.  *    Pointer to Disk_Label if the label was read and converted,
  511.  *    NULL otherwise.
  512.  *
  513.  * Side effects:
  514.  *    Memory allocation
  515.  *
  516.  *----------------------------------------------------------------------
  517.  */
  518.  
  519. static Disk_Label *
  520. ConvertFromSunLabel(fileID, sunLabelPtr)
  521.     int         fileID;        /* Handle on raw disk */
  522.     Sun_DiskLabel    *sunLabelPtr;    /* Sun label to be converted */
  523. {
  524.     Disk_Label        *labelPtr;
  525.     int            i;
  526.     char         buffer[DEV_BYTES_PER_SECTOR * OFS_NUM_DOMAIN_SECTORS];
  527.     Ofs_DomainHeader    *domainHeaderPtr = (Ofs_DomainHeader *) buffer;
  528.     int            sectorsPerCyl;
  529.  
  530.     labelPtr = (Disk_Label *) malloc(sizeof(Disk_Label));
  531.     if (labelPtr == NULL) {
  532.     fprintf(stderr, "Malloc failed.\n");
  533.     return NULL;
  534.     }
  535.     bzero((char *) labelPtr, sizeof(Disk_Label));
  536.     if (sunLabelPtr->magic != SUN_DISK_MAGIC) {
  537.     fprintf(stderr, "Bad magic number on disk <%x> not <%x>\n",
  538.         sunLabelPtr->magic, SUN_DISK_MAGIC);
  539.     }
  540.     if (!CheckSunCheckSum(sunLabelPtr)) {
  541.     printf("Check sum incorrect, 0x%x not 0x%x\n",
  542.         SeeSunCheckSum(sunLabelPtr), sunLabelPtr->checkSum);
  543.     }
  544.     labelPtr->numCylinders = sunLabelPtr->numCylinders;
  545.     labelPtr->numAltCylinders = sunLabelPtr->numAltCylinders;
  546.     labelPtr->numHeads = sunLabelPtr->numHeads;
  547.     labelPtr->numSectors = sunLabelPtr->numSectors;
  548.     labelPtr->asciiLabelLen = 128;
  549.     strncpy(labelPtr->asciiLabel, sunLabelPtr->asciiLabel, 128);
  550.     labelPtr->bootSector = BOOT_SECTOR;
  551.     labelPtr->numDomainSectors = OFS_NUM_DOMAIN_SECTORS;
  552.     /*
  553.      * Go looking for the domain header.  This allows us a variable
  554.      * number of boot sectors, without having to add additional fields
  555.      * to the Sun label.
  556.      */
  557.     for (i = BOOT_SECTOR + 1; 
  558.      i < FSDM_MAX_BOOT_SECTORS + 3; 
  559.      i+= FSDM_BOOT_SECTOR_INC) {
  560.     if (Disk_SectorRead(fileID, i, OFS_NUM_DOMAIN_SECTORS, buffer) < 0) {
  561.         fprintf(stderr, "Can't read sector %d.\n", i);
  562.         return(NULL);
  563.     }
  564.     if (domainHeaderPtr->magic == OFS_DOMAIN_MAGIC) {
  565.         labelPtr->summarySector = i - 1;
  566.         labelPtr->domainSector = i;
  567.         labelPtr->numBootSectors = labelPtr->summarySector - 1;
  568.         break;
  569.     }
  570.     }
  571.     /* 
  572.      * Check if we found a domain header.
  573.      */
  574.     if (i >= FSDM_MAX_BOOT_SECTORS + 3) {
  575.     labelPtr->summarySector = -1;
  576.     labelPtr->domainSector = -1;
  577.     labelPtr->numBootSectors = -1;
  578.     }
  579.     labelPtr->numSummarySectors = 1;
  580.     labelPtr->numPartitions = SUN_NUM_DISK_PARTS;
  581.     sectorsPerCyl = labelPtr->numHeads * labelPtr->numSectors;
  582.     for (i = 0; i < labelPtr->numPartitions; i++) {
  583.     labelPtr->partitions[i].firstCylinder = sunLabelPtr->map[i].cylinder;
  584.     if (sunLabelPtr->map[i].numBlocks % sectorsPerCyl != 0) {
  585.         printf(
  586.     "Warning: size of partition %d (0x%x) is not multiple of cylinder size\n",
  587.             i, sunLabelPtr->map[i].numBlocks);
  588.     }
  589.     labelPtr->partitions[i].numCylinders =     
  590.         sunLabelPtr->map[i].numBlocks / sectorsPerCyl;
  591.     }
  592.     labelPtr->labelSector = SUN_LABEL_SECTOR;
  593.     labelPtr->labelType = DISK_SUN_LABEL;
  594.     labelPtr->labelPtr = (char *) sunLabelPtr;
  595.     return labelPtr;
  596. }
  597. /*
  598.  *----------------------------------------------------------------------
  599.  *
  600.  * ConvertFromDecLabel --
  601.  *
  602.  *    Makes a Disk_Label from a Dec_DiskLabel
  603.  *
  604.  * Results:
  605.  *    Pointer to Disk_Label if the label was read and converted,
  606.  *    NULL otherwise.
  607.  *
  608.  * Side effects:
  609.  *    Memory allocation
  610.  *
  611.  *----------------------------------------------------------------------
  612.  */
  613. /*ARGSUSED*/
  614. static Disk_Label *
  615. ConvertFromDecLabel(fileID, decLabelPtr)
  616.     int         fileID;        /* Handle on raw disk */
  617.     Dec_DiskLabel    *decLabelPtr;    /* DEC label to be converted */
  618. {
  619.     Disk_Label        *labelPtr;
  620.     int            bytesPerCyl;
  621.     int            i;
  622.  
  623.     if (decLabelPtr->numHeads == -1) {
  624.     fprintf(stderr, "Dec label does not have Sprite extensions.\n");
  625.     return NULL;
  626.     }
  627.     labelPtr = (Disk_Label *) malloc(sizeof(Disk_Label));
  628.     if (labelPtr == NULL) {
  629.     fprintf(stderr, "Malloc failed.\n");
  630.     return NULL;
  631.     }
  632.     bzero((char *) labelPtr, sizeof(Disk_Label));
  633.     if (decLabelPtr->magic != DEC_LABEL_MAGIC) {
  634.     printf("Bad magic number on disk <%x> not <%x>\n",
  635.         decLabelPtr->magic, DEC_LABEL_MAGIC);
  636.     }
  637.     labelPtr->numSectors = decLabelPtr->numSectors;
  638.     labelPtr->numHeads = decLabelPtr->numHeads;
  639.     labelPtr->numCylinders = decLabelPtr->numCylinders;
  640.     labelPtr->numAltCylinders = decLabelPtr->numAltCylinders;
  641.     labelPtr->asciiLabelLen = 128;
  642.     strncpy(labelPtr->asciiLabel, decLabelPtr->asciiLabel, 128);
  643.     labelPtr->bootSector = decLabelPtr->bootSector;
  644.     labelPtr->numDomainSectors = decLabelPtr->numDomainSectors;
  645.     labelPtr->numBootSectors = decLabelPtr->numBootSectors;
  646.     labelPtr->summarySector = decLabelPtr->summarySector;
  647.     labelPtr->domainSector = decLabelPtr->domainSector;
  648.     labelPtr->numDomainSectors = decLabelPtr->numDomainSectors;
  649.     labelPtr->numSummarySectors = 1;
  650.     labelPtr->numPartitions = DEC_NUM_DISK_PARTS;
  651.     bytesPerCyl = labelPtr->numHeads * labelPtr->numSectors *
  652.         DEV_BYTES_PER_SECTOR;
  653.     for (i = 0; i < labelPtr->numPartitions; i++) {
  654.     if (decLabelPtr->map[i].offsetBytes % bytesPerCyl != 0) {
  655.         printf(
  656.     "Warning: start of partition %d (0x%x) is not multiple of cylinder size\n",
  657.             i, decLabelPtr->map[i].offsetBytes);
  658.     }
  659.     labelPtr->partitions[i].firstCylinder = 
  660.         decLabelPtr->map[i].offsetBytes / bytesPerCyl;
  661.     if (decLabelPtr->map[i].numBytes % bytesPerCyl != 0) {
  662.         printf(
  663.     "Warning: size of partition %d (0x%x) is not multiple of cylinder size\n",
  664.             i, decLabelPtr->map[i].numBytes);
  665.     }
  666.     labelPtr->partitions[i].numCylinders = 
  667.         decLabelPtr->map[i].numBytes / bytesPerCyl;
  668.     }
  669.     labelPtr->labelSector = DEC_LABEL_SECTOR;
  670.     labelPtr->labelType = DISK_DEC_LABEL;
  671.     labelPtr->labelPtr = (char *) decLabelPtr;
  672.     return labelPtr;
  673. }
  674.  
  675. /*
  676.  *----------------------------------------------------------------------
  677.  *
  678.  *  ConvertToSunLabel --
  679.  *
  680.  *    Makes a Sun_DiskLabel from a Disk_Label
  681.  *
  682.  * Results:
  683.  *    Pointer to Sun_DiskLabel if the label was converted and written,
  684.  *    NULL otherwise.
  685.  *
  686.  * Side effects:
  687.  *    Memory allocation
  688.  *
  689.  *----------------------------------------------------------------------
  690.  */
  691.  
  692. static Sun_DiskLabel *
  693. ConvertToSunLabel(labelPtr)
  694.     Disk_Label        *labelPtr;    /* Label to be converted */
  695. {
  696.     Sun_DiskLabel    *sunLabelPtr;
  697.     int            i;
  698.  
  699.     if (labelPtr->numPartitions > SUN_NUM_DISK_PARTS) {
  700.     fprintf(stderr, "Too many disk partitions for a Sun label (%d > %d)\n",
  701.         labelPtr->numPartitions, SUN_NUM_DISK_PARTS);
  702.     return NULL;
  703.     }
  704.     sunLabelPtr = (Sun_DiskLabel *) malloc(sizeof(Sun_DiskLabel));
  705.     if (sunLabelPtr == NULL) {
  706.     fprintf(stderr, "Malloc failed.\n");
  707.     return NULL;
  708.     }
  709.     bzero((char *) sunLabelPtr, sizeof(Sun_DiskLabel));
  710.     sunLabelPtr->magic = SUN_DISK_MAGIC;
  711.     sunLabelPtr->numCylinders = labelPtr->numCylinders;
  712.     sunLabelPtr->numAltCylinders = labelPtr->numAltCylinders;
  713.     sunLabelPtr->numHeads = labelPtr->numHeads;
  714.     sunLabelPtr->numSectors = labelPtr->numSectors;
  715.     strncpy(sunLabelPtr->asciiLabel, labelPtr->asciiLabel, 128);
  716.     sunLabelPtr->partitionID = 0;
  717.     sunLabelPtr->bhead = 0;
  718.     sunLabelPtr->gap1 = 65535;
  719.     sunLabelPtr->gap2 = 65535;
  720.     sunLabelPtr->interleave = 1;
  721.     for (i = 0; i < SUN_NUM_DISK_PARTS; i++) {
  722.     sunLabelPtr->map[i].cylinder = labelPtr->partitions[i].firstCylinder;
  723.     sunLabelPtr->map[i].numBlocks = labelPtr->partitions[i].numCylinders *
  724.         labelPtr->numHeads * labelPtr->numSectors;
  725.     }
  726.     MakeSunCheckSum(sunLabelPtr);
  727.     return sunLabelPtr;
  728. }
  729. /*
  730.  *----------------------------------------------------------------------
  731.  *
  732.  * ConvertToDecLabel --
  733.  *
  734.  *    Makes a Dec_DiskLabel from a Disk_Label
  735.  *
  736.  * Results:
  737.  *    Pointer to Dec_DiskLabel if the label was converted and written,
  738.  *    NULL otherwise.
  739.  *
  740.  * Side effects:
  741.  *    Memory allocation
  742.  *
  743.  *----------------------------------------------------------------------
  744.  */
  745. static Dec_DiskLabel *
  746. ConvertToDecLabel(labelPtr)
  747.     Disk_Label    *labelPtr;    /* Label to be converted */
  748. {
  749.     Dec_DiskLabel    *decLabelPtr;
  750.     int            bytesPerCyl;
  751.     int            i;
  752.  
  753.     if (labelPtr->numPartitions > DEC_NUM_DISK_PARTS) {
  754.     fprintf(stderr, "Too many disk partitions for a DEC label (%d > %d)\n",
  755.         labelPtr->numPartitions, DEC_NUM_DISK_PARTS);
  756.     return NULL;
  757.     }
  758.     decLabelPtr = (Dec_DiskLabel *) malloc(sizeof(Dec_DiskLabel));
  759.     if (decLabelPtr == NULL) {
  760.     fprintf(stderr, "Malloc failed.\n");
  761.     return NULL;
  762.     }
  763.     bzero((char *) decLabelPtr, sizeof(Dec_DiskLabel));
  764.     decLabelPtr->magic = DEC_LABEL_MAGIC;
  765.     decLabelPtr->spriteMagic = FSDM_DISK_MAGIC;
  766.     decLabelPtr->version = DEC_LABEL_VERSION;
  767.     decLabelPtr->isPartitioned = 1;
  768.     decLabelPtr->numHeads = labelPtr->numHeads;
  769.     decLabelPtr->numSectors = labelPtr->numSectors;
  770.     decLabelPtr->domainSector = labelPtr->domainSector;
  771.     decLabelPtr->numDomainSectors = labelPtr->numDomainSectors;
  772.     decLabelPtr->numCylinders = labelPtr->numCylinders;
  773.     decLabelPtr->numAltCylinders = labelPtr->numAltCylinders;
  774.     decLabelPtr->bootSector = labelPtr->bootSector;
  775.     decLabelPtr->numBootSectors = labelPtr->numBootSectors;
  776.     decLabelPtr->summarySector = labelPtr->summarySector;
  777.     strncpy(decLabelPtr->asciiLabel, labelPtr->asciiLabel, 128);
  778.     bytesPerCyl = labelPtr->numHeads *labelPtr->numSectors *
  779.         DEV_BYTES_PER_SECTOR;
  780.     for (i = 0; i < DEC_NUM_DISK_PARTS; i++) {
  781.     decLabelPtr->map[i].numBytes = 
  782.         labelPtr->partitions[i].numCylinders * bytesPerCyl;
  783.     decLabelPtr->map[i].offsetBytes = 
  784.         labelPtr->partitions[i].firstCylinder * bytesPerCyl;
  785.     }
  786.     return decLabelPtr;
  787. }
  788.  
  789. /*
  790.  *----------------------------------------------------------------------
  791.  *
  792.  * Sun checksum routines --
  793.  *
  794.  *    The following routines manipulate the checksum in a Sun label.
  795.  *
  796.  * Results:
  797.  *    None.
  798.  *
  799.  * Side effects:
  800.  *    None.
  801.  *
  802.  *----------------------------------------------------------------------
  803.  */
  804.  
  805. static short
  806. SeeSunCheckSum(sunLabelPtr)
  807.     Sun_DiskLabel *sunLabelPtr;
  808. {
  809.         short *sp, sum = 0;
  810.         short count = DEV_BYTES_PER_SECTOR/sizeof(short) - 1;
  811.  
  812.         sp = (short *)sunLabelPtr;
  813.         while (count--)
  814.                 sum ^= *sp++;
  815.         return (sum);
  816. }
  817.  
  818. static int
  819. CheckSunCheckSum(sunLabelPtr)
  820.     Sun_DiskLabel *sunLabelPtr;
  821. {
  822.         short *sp, sum = 0;
  823.         short count = DEV_BYTES_PER_SECTOR/sizeof(short);
  824.  
  825.         sp = (short *)sunLabelPtr;
  826.         while (count--)
  827.                 sum ^= *sp++;
  828.         return (sum ? 0 : 1);
  829. }
  830.  
  831. static int
  832. MakeSunCheckSum(sunLabelPtr)
  833.     Sun_DiskLabel *sunLabelPtr;
  834. {
  835.         short *sp, sum = 0;
  836.         short count = DEV_BYTES_PER_SECTOR/sizeof(short) - 1;
  837.  
  838.         sunLabelPtr->checkSum = 0;
  839.         sp = (short *)sunLabelPtr;
  840.         while (count--)
  841.                 sum ^= *sp++;
  842.         sunLabelPtr->checkSum = sum;
  843. }
  844.  
  845. /*
  846.  *----------------------------------------------------------------------
  847.  *
  848.  * Disk_EraseLabel --
  849.  *
  850.  *    Erase a label from the disk.
  851.  *
  852.  * Results:
  853.  *    0 if the label was erased properly
  854.  *    -1 otherwise.
  855.  *
  856.  * Side effects:
  857.  *    A sector is cleared on the disk.
  858.  *
  859.  *----------------------------------------------------------------------
  860.  */
  861.  
  862. int
  863. Disk_EraseLabel(fileID, labelType)
  864.     int                fileID;        /* Handle on raw disk. */
  865.     Disk_NativeLabelType    labelType;    /* Type of label. */
  866. {
  867.     char    buffer[DEV_BYTES_PER_SECTOR];
  868.     int        sector;
  869.  
  870.     switch (labelType) {
  871.     case DISK_SUN_LABEL:
  872.         sector = SUN_LABEL_SECTOR;
  873.         break;
  874.     case DISK_DEC_LABEL:
  875.         sector = DEC_LABEL_SECTOR;
  876.         break;
  877.     default:
  878.         printf("Unknown label type.\n");
  879.         return -1;
  880.     }
  881.     bzero(buffer, DEV_BYTES_PER_SECTOR);
  882.     return Disk_SectorWrite(fileID, sector, 1, buffer);
  883. }
  884.  
  885. /*
  886.  *----------------------------------------------------------------------
  887.  *
  888.  * Disk_HasFilesystem
  889.  *
  890.  *    Determines if a filesystem can be found on the disk stream.
  891.  *
  892.  * Results:
  893.  *    DISK_HAS_NO_FS if no filesystem could be found;
  894.  *      DISK_HAS_OFS if an old filesystem was found;
  895.  *      DISK_HAS_LFS if a log structured filesystem was found;
  896.  *
  897.  * Side effects:
  898.  *    Memory allocation.
  899.  *
  900.  *----------------------------------------------------------------------
  901.  */
  902. int
  903. Disk_HasFilesystem(fileID, diskLabelPtr)
  904.     int fileID;                /* Disk stream */
  905.     Disk_Label *diskLabelPtr;  /* Disk Label */ 
  906. {
  907.     Ofs_DomainHeader *headerPtr;
  908.     LfsSuperBlock    *superPtr;
  909.     int              status;
  910.     unsigned int     magic;
  911.  
  912.     /*
  913.      * Note: We check for an OFS first because when an OFS is created
  914.      *       the old filesystem on the disk is not explicitly erased.
  915.      *       So if the old filesystem was a LFS, is is possible that
  916.      *       the LfsSuperBlock is still on the disk.  'fsmake' should
  917.      *       be changed to erase the old filesystem, but since the OFS
  918.      *       is rarely used it is not crucial.  'mklfs' does the
  919.      *       right thing.
  920.      *
  921.      *       Also, Disk_ReadDomainHeader() and Disk_ReadLfsSuperBlock()
  922.      *       were not used because we don't want any error messages
  923.      *       printed out.
  924.      */
  925.  
  926.     /*
  927.      * check for an OFS by trying to read a domain header.  If one
  928.      * is found that has a valid magic number, then assume that
  929.      * an OFS is on the disk
  930.      */
  931.     headerPtr = (Ofs_DomainHeader *)malloc((unsigned) 
  932.     (diskLabelPtr->numDomainSectors * DEV_BYTES_PER_SECTOR));
  933.     if (headerPtr == NULL) {
  934.     perror("Disk_HasFilesystem:  allocating Ofs_DomainHeader");
  935.     exit(FAILURE);
  936.     }
  937.     /*
  938.      * if the domainSector is negative, then there is no Ofs_DomainHeader
  939.      * on the disk -- just check to see if it is an LFS then...
  940.      */
  941.     if (diskLabelPtr -> domainSector >= 0 && 
  942.     diskLabelPtr -> summarySector >= 0 ) {
  943.     status = Disk_SectorRead(fileID, diskLabelPtr -> domainSector,
  944.                  diskLabelPtr -> numDomainSectors,
  945.                  (Address)headerPtr);
  946.     magic = headerPtr -> magic;
  947.     free(headerPtr);
  948.     } else {
  949.     status = -1;
  950.     }
  951.     if (status < 0 || magic != OFS_DOMAIN_MAGIC) {
  952.     /*
  953.      * check for a LFS by trying to read a LfsSuperBlock.  If
  954.      * one is found that has a valid magic number, then assume that
  955.      * a LFS is on the disk
  956.      */
  957.     superPtr = (LfsSuperBlock *)malloc(LFS_SUPER_BLOCK_SIZE);
  958.     if (superPtr == NULL) {
  959.         perror("Disk_HasFilesystem:  allocating LfsSuperBlock");
  960.         exit(FAILURE);
  961.     }
  962.     status = Disk_SectorRead(fileID, LFS_SUPER_BLOCK_OFFSET,
  963.                  LFS_SUPER_BLOCK_SIZE / DEV_BYTES_PER_SECTOR,
  964.                  (Address)superPtr);
  965.     magic = superPtr ->hdr.magic;
  966.     free(superPtr);
  967.     if (status < 0 || magic != LFS_SUPER_BLOCK_MAGIC) {
  968.         return DISK_HAS_NO_FS;
  969.     } else {
  970.         return DISK_HAS_LFS;
  971.     }
  972.     } else {
  973.     return DISK_HAS_OFS;
  974.     }
  975. }
  976.  
  977. /*
  978.  *----------------------------------------------------------------------
  979.  *
  980.  * Disk_ReadLfsSuperBlock
  981.  *
  982.  *    Read the LFS SuperBlock from the stream.
  983.  *
  984.  * Results:
  985.  *    A pointer to the LFS SuperBlock if could read it, NULL otherwise.
  986.  *
  987.  * Side effects:
  988.  *    Memory allocation.
  989.  *
  990.  *----------------------------------------------------------------------
  991.  */
  992. LfsSuperBlock *
  993. Disk_ReadLfsSuperBlock(fileID, diskLabelPtr)
  994.     int fileID;                /* Disk stream */
  995.     Disk_Label *diskLabelPtr;  /* Disk Label */
  996. {
  997.     LfsSuperBlock    *superPtr;
  998.     int              fstype, status;
  999.     
  1000.     fstype = Disk_HasFilesystem(fileID, diskLabelPtr);
  1001.     if (fstype != DISK_HAS_LFS) {
  1002.     return ((LfsSuperBlock *)NULL);
  1003.     }
  1004.     /*
  1005.      * Note:  Reading of LfsSuperBlock is dependent on the blockSize constant
  1006.      * set at the top of /sprite/src/admin/mklfs/mklfs.c
  1007.      */
  1008.     superPtr = (LfsSuperBlock *)malloc(LFS_SUPER_BLOCK_SIZE);
  1009.     if (superPtr == NULL) {
  1010.     perror("Disk_ReadLfsSuperBlock: allocating LfsSuperBlock");
  1011.     exit(FAILURE);
  1012.     }
  1013.     status = Disk_SectorRead(fileID, LFS_SUPER_BLOCK_OFFSET,
  1014.                  LFS_SUPER_BLOCK_SIZE / DEV_BYTES_PER_SECTOR,
  1015.                  (Address)superPtr);
  1016.     if (status < 0) {
  1017.     free((Address)superPtr);
  1018.     return ((LfsSuperBlock *)0);
  1019.     } else {
  1020.     if (superPtr -> hdr.magic != LFS_SUPER_BLOCK_MAGIC) {
  1021.         fprintf(stderr, "Disk_ReadLfsSuperBlock, bad magic <%x>\n",
  1022.             superPtr -> hdr.magic);
  1023.         free((Address)superPtr);
  1024.         return ((LfsSuperBlock *)0);
  1025.     } else {
  1026.         return superPtr;
  1027.     }
  1028.     }
  1029. }
  1030.  
  1031. /*
  1032.  *----------------------------------------------------------------------
  1033.  *
  1034.  * Disk_WriteLfsSuperBlock
  1035.  *
  1036.  *    Write the LFS SuperBlock to the stream.
  1037.  *
  1038.  * Results:
  1039.  *    -1 if the SuperBlock could not be written, 0 if it could.
  1040.  *
  1041.  * Side effects:
  1042.  *    Does the write.
  1043.  *
  1044.  *----------------------------------------------------------------------
  1045.  */
  1046. ReturnStatus
  1047. Disk_WriteLfsSuperBlock(fileID, superPtr)
  1048.     int         fileID;            /* Stream to raw disk */
  1049.     LfsSuperBlock    *superPtr;        /* Lfs SuperBlock */
  1050. {
  1051.     return Disk_SectorWrite(fileID, LFS_SUPER_BLOCK_OFFSET,
  1052.             LFS_SUPER_BLOCK_SIZE / DEV_BYTES_PER_SECTOR, 
  1053.             (Address)superPtr);
  1054. }
  1055.  
  1056. /*
  1057.  *----------------------------------------------------------------------
  1058.  *
  1059.  * Disk_ReadLfsCheckPointHdr
  1060.  *
  1061.  *    Read the current checkpoint region in its entirety.  The caller
  1062.  *      can choose which checkpoint region to read by specifying 
  1063.  *      either `0' or `1' in the area argument (any other value
  1064.  *      will return the current checkpoint).
  1065.  *
  1066.  * Results:
  1067.  *    A pointer to the header of the checkpoint region upon
  1068.  *      success, NULL otherwise.  Using the header, the other
  1069.  *      sections of the checkpoint can be reached.
  1070.  *
  1071.  * Side effects:
  1072.  *    Memory allocation.
  1073.  *
  1074.  *----------------------------------------------------------------------
  1075.  */
  1076. LfsCheckPointHdr *
  1077. Disk_ReadLfsCheckPointHdr(fileID, labelPtr, areaPtr)
  1078.     int        fileID;
  1079.     Disk_Label *labelPtr;
  1080.     int        *areaPtr;       /* return value specifying checkpoint area */
  1081. {
  1082.     LfsSuperBlock        *superPtr;
  1083.     LfsCheckPointHdr     *checkPointHdrPtr;
  1084.     LfsCheckPointTrailer *trailerPtr;
  1085.     int                  checkPointOffset, checkPointSize;
  1086.     int                  numSectors;
  1087.     char                 *bufferPtr;
  1088.     unsigned int         stamp0, stamp1;
  1089.     int                  status;
  1090.     
  1091.     superPtr = Disk_ReadLfsSuperBlock(fileID, labelPtr);
  1092.     if (superPtr == NULL) {
  1093.     return ((LfsCheckPointHdr *)NULL);
  1094.     }
  1095.     /*
  1096.      * Examine the two checkpoint areas to locate the checkpoint area with the
  1097.      * newest timestamp.
  1098.      */
  1099.     numSectors = ((sizeof(LfsCheckPointHdr) + DEV_BYTES_PER_SECTOR) - 1) /
  1100.              DEV_BYTES_PER_SECTOR;
  1101.     bufferPtr = (char *)malloc(numSectors * DEV_BYTES_PER_SECTOR);
  1102.     if (bufferPtr == NULL) {
  1103.     perror("Disk_ReadLfsCheckPointHdr: allocating LfsCheckPointHdr");
  1104.     exit(FAILURE);
  1105.     }
  1106.     /*
  1107.      * Checkpoint region one.
  1108.      */
  1109.     status = Disk_SectorRead(fileID, superPtr -> hdr.checkPointOffset[0],
  1110.                  numSectors, bufferPtr);
  1111.     if (status < 0) {
  1112.     fprintf(stderr, "Disk_ReadCheckPointHdr: could not read header #0\n");
  1113.     free(bufferPtr);
  1114.     free(superPtr);
  1115.     return (LfsCheckPointHdr *)NULL;
  1116.     }
  1117.     stamp0 = ((LfsCheckPointHdr *)bufferPtr) -> timestamp;
  1118.     /*
  1119.      * Checkpoint region two.
  1120.      */
  1121.     status = Disk_SectorRead(fileID, superPtr -> hdr.checkPointOffset[1],
  1122.                  numSectors, bufferPtr);
  1123.     if (status < 0) {
  1124.     fprintf(stderr, "Disk_ReadCheckPointHdr: could not read header #1\n");
  1125.     free(bufferPtr);
  1126.     free(superPtr);
  1127.     return (LfsCheckPointHdr *)NULL;
  1128.     }
  1129.     stamp1 = ((LfsCheckPointHdr *)bufferPtr) -> timestamp;
  1130.     free(bufferPtr);
  1131.     /*
  1132.      * Get the latest checkpoint header, and return in `areaPtr' 
  1133.      * which checkpoint area the header is for. (It should be in the
  1134.      * structure, but it's not so oh well.)  If `areaPtr' 
  1135.      * specifies which area to get, then get that one.
  1136.      */
  1137.     if (areaPtr != NULL && *areaPtr == 0) {
  1138.     checkPointOffset = superPtr -> hdr.checkPointOffset[0];
  1139.     } else if (areaPtr != NULL && *areaPtr == 1) {
  1140.     checkPointOffset = superPtr -> hdr.checkPointOffset[1];
  1141.     } else if (stamp0 < stamp1) {
  1142.     if (areaPtr != NULL) {
  1143.         *areaPtr = 1;
  1144.     }
  1145.     checkPointOffset = superPtr -> hdr.checkPointOffset[1];
  1146.     } else {
  1147.     if (areaPtr != NULL) {
  1148.         *areaPtr = 0;
  1149.     }
  1150.     checkPointOffset = superPtr -> hdr.checkPointOffset[0];
  1151.     }
  1152.  
  1153.     checkPointSize = superPtr -> hdr.maxCheckPointBlocks *
  1154.                  superPtr -> hdr.blockSize;
  1155.     checkPointHdrPtr = (LfsCheckPointHdr *)malloc(checkPointSize);
  1156.     if (checkPointHdrPtr == NULL) {
  1157.     perror("allocating buffer for a full Lfs CheckPoint");
  1158.     exit(FAILURE);
  1159.     }
  1160.     status = Disk_SectorRead(fileID, checkPointOffset, 
  1161.                  superPtr -> hdr.maxCheckPointBlocks,
  1162.                  (Address)checkPointHdrPtr);
  1163.     free(superPtr);
  1164.     if (status < 0) {
  1165.     fprintf(stderr, "cannot read the entire checkpoint region");
  1166.     free(checkPointHdrPtr);
  1167.     return (LfsCheckPointHdr *)NULL;
  1168.     }
  1169.     /*
  1170.      * if we cannot find a valid trailer, then the checkpoint is not valid
  1171.      */
  1172.     trailerPtr = Disk_LfsCheckPointTrailer(checkPointHdrPtr);
  1173.     if (trailerPtr == NULL) {
  1174.     free(checkPointHdrPtr);
  1175.     return (LfsCheckPointHdr *)NULL;
  1176.     }
  1177.     return checkPointHdrPtr;
  1178. }
  1179.  
  1180. /*
  1181.  *----------------------------------------------------------------------
  1182.  *
  1183.  * Disk_WriteLfsCheckPointHdr
  1184.  *
  1185.  *    Write the checkpoint header only.
  1186.  *
  1187.  * Results:
  1188.  *    0 if the header was successfully written, -1 if it wasn't.
  1189.  *
  1190.  * Side effects:
  1191.  *    Disk write.
  1192.  *
  1193.  *----------------------------------------------------------------------
  1194.  */
  1195. ReturnStatus
  1196. Disk_WriteLfsCheckPointHdr(fileID, headerPtr, area, labelPtr)
  1197.     int              fileID;
  1198.     LfsCheckPointHdr *headerPtr;
  1199.     int              area;   /* which checkpoint area this is: 0 or 1 */
  1200.     Disk_Label       *labelPtr;
  1201. {
  1202.     LfsSuperBlock *superPtr;
  1203.     int           numSectors;
  1204.     int           status;
  1205.  
  1206.     if (area < 0 || area > 1) {
  1207.     return -1;
  1208.     }
  1209.     superPtr = Disk_ReadLfsSuperBlock(fileID, labelPtr);
  1210.     if (superPtr == NULL) {
  1211.     return -1;
  1212.     }
  1213.     numSectors = ((sizeof(LfsCheckPointHdr) + DEV_BYTES_PER_SECTOR) - 1) /
  1214.              DEV_BYTES_PER_SECTOR;
  1215.     status = Disk_SectorWrite(fileID, superPtr->hdr.checkPointOffset[area],
  1216.                  numSectors, (Address)headerPtr);
  1217.     return status;
  1218. }
  1219.  
  1220. /*
  1221.  *----------------------------------------------------------------------
  1222.  *
  1223.  * Disk_WriteLfsCheckPointArea
  1224.  *
  1225.  *    Write the checkpoint area, headed by an LfsCheckPointHdr,
  1226.  *      to disk.  Such an area is returned from Disk_ReadLfsCheckPointHdr().
  1227.  *      Note: this does not constitute an update.
  1228.  *
  1229.  * Results:
  1230.  *    0 if the area was successfully written, -1 if it wasn't.
  1231.  *
  1232.  * Side effects:
  1233.  *    Disk write.
  1234.  *
  1235.  *----------------------------------------------------------------------
  1236.  */
  1237. ReturnStatus
  1238. Disk_WriteLfsCheckPointArea(fileID, areaPtr, area, labelPtr)
  1239.     int              fileID;
  1240.     LfsCheckPointHdr *areaPtr;
  1241.     int              area;  /* which checkpoint area this is: 0 or 1 */
  1242.     Disk_Label       *labelPtr;
  1243. {
  1244.     LfsSuperBlock *superPtr;
  1245.     int           status;
  1246.  
  1247.     if (area < 0 || area > 1) {
  1248.     return -1;
  1249.     }
  1250.     superPtr = Disk_ReadLfsSuperBlock(fileID, labelPtr);
  1251.     if (superPtr == NULL) {
  1252.     return -1;
  1253.     }
  1254.     status = Disk_SectorWrite(fileID, 
  1255.                   superPtr->hdr.checkPointOffset[area],
  1256.                   superPtr->hdr.maxCheckPointBlocks,
  1257.                   (Address)areaPtr);
  1258.     return status;
  1259. }
  1260.  
  1261. /*
  1262.  *----------------------------------------------------------------------
  1263.  *
  1264.  * Disk_LfsCheckPointTrailer
  1265.  *
  1266.  *    Find the trailer of the checkpoint region using the checkpoint header
  1267.  *
  1268.  * Results:
  1269.  *    A pointer to the trailer of the checkpoint region upon
  1270.  *      success, NULL otherwise.  
  1271.  *
  1272.  *      Note: the pointer returned is a pointer into the header.
  1273.  *
  1274.  * Side effects:
  1275.  *    None.
  1276.  *
  1277.  *----------------------------------------------------------------------
  1278.  */
  1279. LfsCheckPointTrailer *
  1280. Disk_LfsCheckPointTrailer(checkPointPtr)
  1281.     LfsCheckPointHdr *checkPointPtr;
  1282. {
  1283.     char                 *bytePtr;
  1284.     LfsCheckPointTrailer *trailerPtr;
  1285.  
  1286.     bytePtr = (char *)checkPointPtr;
  1287.     trailerPtr = (checkPointPtr == NULL) ? (LfsCheckPointTrailer *)NULL :
  1288.     (LfsCheckPointTrailer *)(bytePtr + checkPointPtr -> size -
  1289.                  sizeof(LfsCheckPointTrailer));
  1290.     if (trailerPtr == NULL) {
  1291.     fprintf(stderr, "Lfs CheckPoint does not have a valid trailer\n");
  1292.     return (LfsCheckPointTrailer *)NULL;
  1293.     } else if (checkPointPtr -> timestamp != trailerPtr -> timestamp) {
  1294.     fprintf(stderr, "CheckPoint header timestamp <%d> does not match\n",
  1295.         checkPointPtr -> timestamp);
  1296.     fprintf(stderr, "trailer timestamp <%d>.\n", trailerPtr -> timestamp);
  1297.     return (LfsCheckPointTrailer *)NULL;
  1298.     }
  1299.     return trailerPtr;
  1300. }
  1301.  
  1302. /*
  1303.  *----------------------------------------------------------------------
  1304.  *
  1305.  * Disk_ForEachCheckPointRegion
  1306.  *
  1307.  *    For every checkpoint region found in the checkpoint header,
  1308.  *      execute the procedure argument on that region.  The procedure
  1309.  *      argument must take a LfsCheckPointRegion pointer as an
  1310.  *      argument, and have a return value of ReturnStatus.  If the
  1311.  *      procedure returns a non-zero return value, the region iteration
  1312.  *      stops and that value is returned.
  1313.  *
  1314.  * Results:
  1315.  *      0 if there were no problems and the procedure was invoked
  1316.  *        with every checkpoit region as an argument;
  1317.  *    -1 if the trailer could not be found from the header;
  1318.  *      a non-zero return value from the procedure argument.
  1319.  *
  1320.  * Side effects:
  1321.  *    None.
  1322.  *
  1323.  *----------------------------------------------------------------------
  1324.  */
  1325. ReturnStatus
  1326. Disk_ForEachCheckPointRegion(checkPointPtr, regionProc)
  1327.     LfsCheckPointHdr *checkPointPtr;
  1328.     ReturnStatus (*regionProc)();
  1329. {
  1330.     char                 *bytePtr, *maxBytePtr;
  1331.     LfsCheckPointTrailer *trailerPtr;
  1332.     LfsCheckPointRegion  *regionPtr;
  1333.     ReturnStatus status;
  1334.  
  1335.     status = 0;
  1336.     trailerPtr = Disk_LfsCheckPointTrailer(checkPointPtr);
  1337.     if (trailerPtr == NULL) {
  1338.     return -1;
  1339.     }
  1340.     bytePtr = (char *)checkPointPtr;
  1341.     bytePtr += sizeof(LfsCheckPointHdr);
  1342.     maxBytePtr = (char *)trailerPtr;
  1343.     while (bytePtr < maxBytePtr) {
  1344.     regionPtr = (LfsCheckPointRegion *)bytePtr;
  1345.     status = regionProc(regionPtr);
  1346.     if (status) {
  1347.         return status;
  1348.     }
  1349.     bytePtr += regionPtr -> size;
  1350.     }
  1351.     return 0;
  1352. }
  1353.  
  1354.  
  1355. /*
  1356.  *----------------------------------------------------------------------
  1357.  *
  1358.  * Disk_ReadLfsSegSummary --
  1359.  *
  1360.  *    Reads a segment summary block from an LFS segment. Each segment
  1361.  *    contains a linked list of summary blocks. To read the first
  1362.  *    one pass NULL as the prevSegPtr. For subsequent summary blocks
  1363.  *    pass in a pointer to the previous block.
  1364.  *
  1365.  * Results:
  1366.  *    Pointer to the segment summary block, or NULL if the indicated
  1367.  *    block doesn't exist.
  1368.  *
  1369.  * Side effects:
  1370.  *    None.
  1371.  *
  1372.  *----------------------------------------------------------------------
  1373.  */
  1374.  
  1375. LfsSegSummary    *
  1376. Disk_ReadLfsSegSummary(fileID, superPtr, segment, prevSegPtr)
  1377.     int            fileID;        /* Stream to raw disk. */
  1378.     LfsSuperBlock    *superPtr;    /* Lfs SuperBlock */
  1379.     int            segment;    /* Segment # to use. */
  1380.     LfsSegSummary    *prevSegPtr;    /* Previous segment summary block
  1381.                      * for the segment. */
  1382.  
  1383. {
  1384.     int            blockOffset = 1;
  1385.     LfsSegSummary    *segPtr;
  1386.     int            status;
  1387.     int            segOffset;
  1388.     int            blocksPerSeg;
  1389.  
  1390.     if (prevSegPtr != NULL) {
  1391.     blockOffset = prevSegPtr->nextSummaryBlock;
  1392.     }
  1393.     blocksPerSeg = superPtr->usageArray.segmentSize/DEV_BYTES_PER_SECTOR;
  1394.     segPtr = (LfsSegSummary *) malloc(DEV_BYTES_PER_SECTOR);
  1395.     segOffset = segment * blocksPerSeg + superPtr->hdr.logStartOffset;
  1396.     status = Disk_SectorRead(fileID, segOffset + blocksPerSeg - blockOffset,
  1397.         1, (Address) segPtr);
  1398.     if (status < 0) {
  1399.     free((char *) segPtr);
  1400.     return NULL;
  1401.     }
  1402.     return segPtr;
  1403. }
  1404.  
  1405.  
  1406. /*
  1407.  *----------------------------------------------------------------------
  1408.  *
  1409.  * Disk_WriteLfsSegSummary --
  1410.  *
  1411.  *    Writes a segment summary block to an LFS segment. To write the first
  1412.  *    one pass NULL as the prevSegPtr. For subsequent summary blocks
  1413.  *    pass in a pointer to the previous block.
  1414.  *
  1415.  * Results:
  1416.  *    Standard return status.
  1417.  *
  1418.  * Side effects:
  1419.  *    None.
  1420.  *
  1421.  *----------------------------------------------------------------------
  1422.  */
  1423.  
  1424. ReturnStatus
  1425. Disk_WriteLfsSegSummary(fileID, superPtr, segment, prevSegPtr, segPtr)
  1426.     int            fileID;        /* Stream to raw disk. */
  1427.     LfsSuperBlock    *superPtr;    /* Lfs SuperBlock */
  1428.     int            segment;    /* Segment # to use. */
  1429.     LfsSegSummary    *prevSegPtr;    /* Previous segment summary block
  1430.                      * for the segment. */
  1431.     LfsSegSummary    *segPtr;    /* Segment to write. */
  1432. {
  1433.     int            blockOffset = 1;
  1434.     int            status;
  1435.     int            segOffset;
  1436.     int            blocksPerSeg;
  1437.  
  1438.     if (prevSegPtr != NULL) {
  1439.     blockOffset = prevSegPtr->nextSummaryBlock;
  1440.     }
  1441.     blocksPerSeg = superPtr->usageArray.segmentSize/DEV_BYTES_PER_SECTOR;
  1442.     segOffset = segment * blocksPerSeg + superPtr->hdr.logStartOffset;
  1443.     status = Disk_SectorWrite(fileID, segOffset + blocksPerSeg - blockOffset,
  1444.         1, (Address) segPtr);
  1445.     if (status < 0) {
  1446.     return FAILURE;
  1447.     }
  1448.     return SUCCESS;
  1449. }
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.